package edu.maping.easy.painter;

import java.util.ArrayList;
import java.util.List;

import napplet.EMNit;
import napplet.InterfazPlayPause;

import controlP5.Bang;
import controlP5.CheckBox;
import controlP5.ControlEvent;
import controlP5.ControlGroup;
import controlP5.ControlP5;
import controlP5.Controller;
import controlP5.Radio;
import controlP5.RadioButton;
import controlP5.ScrollList;
import edu.maping.easy.ControlFacade;
import edu.maping.easy.gui.Button;
import edu.maping.easy.gui.ButtonList;
import edu.maping.easy.gui.CircleButton;
import edu.maping.easy.gui.GUIEvent;
import edu.maping.easy.gui.GuiFactory;
import edu.maping.easy.model.GUIInteraction;
import edu.maping.easy.model.Point;
import edu.maping.easy.model.Thing;
import edu.maping.easy.model.World;
import edu.maping.easy.painter.cornerpin.CornerPin;
import edu.maping.easy.painter.plugins.TimeRunner;
import edu.maping.easy.sequence.ActionConf;
import edu.maping.easy.sequence.ActionEvent;
import edu.maping.easy.sequence.ActionEventList;
import edu.maping.easy.sequence.PropagationManager;
import edu.maping.easy.sequence.SequenceStep;
import edu.maping.easy.sequence.ticker.PropagationTicker;
import edu.maping.easy.sequence.ticker.Ticker;
import edu.maping.easy.sequence.ticker.TickerListener;
import edu.maping.easy.sequence.ticker.TimeTicker;
import fisica.FBody;

import processing.core.PApplet;

/*
 * Esta clase maneja el listado de renderers, y el acceso a sus formularios de configuración
 * 
 */

public class PolygonRendererManager extends ArrayList<PainterContainer> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6582581204940863796L;

	private ButtonList scrollList = null;
	private ButtonList tickersList = null;
	List<Ticker> tickers = new ArrayList<Ticker>();

	private ArrayList<FBody> buttons = new ArrayList<FBody>();

	private ArrayList<ButtonList> controlGroups = new ArrayList<ButtonList>();

	private int lastX = 0;
	private int lastY = 0;

	private PainterContainer painterContainer = null;
	private PApplet pApplet;
	private ControlFacade controlFacade;

	public final static String ON = "ON";
	public final static String OFF = "OFF";
	private static String CLEAR = "CLEAR";
	private static String CLOSE = "CLOSE";
	private static String TICKERS = "Tickers";
	private static String CORNERPIN = "CornerPin";
	private static String PROPAGATION = "Propagation";

	private Button closeButton = null;
	private ButtonList form;

	private List<ActionEvent> actionEvents;
	private ActionEvent currentActionEvent;

	private boolean doing = false;

	private Thing currentThing = null;

	private GuiFactory guiFactory;
	// private Ticker editingTicker;
	public PropagationManager propagationManager;

	public SequenceStep thingActionEvent;

	private Point thingPosition = new Point(0, 0);
	private Point currentPosition = null;
	private Point currentDelegatePosition = new Point(0, 0);

	public List<ActionEvent> getActionEvents() {
		return actionEvents;
	}

	public void render(Point p, ActionEventList current, Thing currentThing) {

		if (currentActionEvent != null)
			return;

		this.actionEvents = current;
		this.currentThing = currentThing;

		thingPosition.setX(currentThing.getX());
		thingPosition.setY(currentThing.getY());

		currentPosition = p;

		// for (int index = 0; index < buttons.size(); index++) {
		// // buttons.get(index).setFillColor(-16763310);
		// scrollList.add(buttons.get(index));
		// }
		scrollList.init();

		for (int index2 = 0; index2 < actionEvents.size(); index2++) {
			ActionEvent actionEvent = actionEvents.get(index2);
			String name = actionEvent.painterContainer.painterDelegate
					.getName();
			boolean finded = false;
			// for (int index = 0; index < buttons.size(); index++) {
			// if (buttons.get(index).equals(name)) {
			// buttons.get(index).setFillColor(-16777216);
			// finded = true;
			// break;
			// }
			// }

			// if (!finded) {
			// System.out
			// .println("error al manejar la activación de los painters con datos");
			// }

		}

		scrollList.setPosition(p.x, p.y);
		scrollList.setDrawable(true);
		lastX = p.x;
		lastY = p.y;
		doing = true;

	}

	public void setup(PApplet pApplet, World world,
			ControlFacade controlFacade, GuiFactory guiFactory) {

		this.guiFactory = guiFactory;
		// scrollList = controlP5.addScrollList("pluginList", 0, 0, 75, 200);
		scrollList = guiFactory.newButtonList("Renderers", 50, 50, 1, 1);
		tickersList = guiFactory.newButtonList("TickerList", 50, 50, 1, 1);
		scrollList.setDrawable(false);
		tickersList.setDrawable(false);
		tickersList.setGrabbable(true);

		this.pApplet = pApplet;
		this.controlFacade = controlFacade;

		// closeButton = scrollList.addItem("CERRAR", 0);
		closeButton = guiFactory.newButton(CLOSE, scrollList.getX(),
				scrollList.getY(), 30, 20);
		scrollList.add(closeButton);

	}

	public ActionEvent controlEvent(GUIEvent theEvent) {

		if (!doing) {
			return null;
		}

		closeRendererListIfSelect(theEvent);

		if (painterContainer != null) {
			// CONFIGURING ONE PAINTERDELEGATE

			// if (theEvent.isController()) {
			ActionEvent actionEvent = onOffCloseOperations(theEvent);
			if (actionEvent != null) {
				return actionEvent;
			}
			// }

			// CHECKS IF ANY TICKER WAS PRESSED
			int index = tickersList.indexOf(theEvent.controller());
			if (index >= 0) {
				Ticker mainTicker = tickers.get(index);
				currentActionEvent.ticker = mainTicker.newTicker();
				// editingTicker = mainTicker;
				mainTicker.setReadyToNewTicker();
				tickersList.setDrawable(false);
			}

			if (currentActionEvent != null) {
				currentActionEvent.actionConf.controlEvent(theEvent);
				currentActionEvent.painterContainer.painterDelegate
						.controlEvent(theEvent);
			} else {
				System.out
						.println("Este caso  hay que analizarlo, si tengo thingPainter, tengo actionEvent");
			}

			return null;
		} else {

			// if (theEvent.isController()) {
			int index = buttons.indexOf(theEvent.controller());
			if (index >= 0) {
				// OPEN RENDER CONFIG DIALOG
				painterContainer = get(index);
				painterContainer.painterDelegate.showForm(lastX + 90, lastY);
				InterfazPlayPause emNit = (InterfazPlayPause) painterContainer.painterDelegate;
				emNit.play();
				painterContainer.painterDelegate.setThing(currentThing);
				loadOrCreateActionEvent(actionEvents);
			}
		}
		// }

		return null;
	}

	private void loadOrCreateActionEvent(List<ActionEvent> currentAEventList) {

		boolean find = false;

		for (int index2 = 0; index2 < currentAEventList.size(); index2++) {
			ActionEvent actionEvent = currentAEventList.get(index2);

			String name1 = painterContainer.painterDelegate.getName();
			String name2 = actionEvent.painterContainer.painterDelegate
					.getName();

			if (name1 != null && name1.equals(name2)) {

				currentActionEvent = actionEvent;
				find = true;

			}
		}

		if (find) {
			if (currentActionEvent.actionConf == null) {
				currentActionEvent.actionConf = painterContainer.painterDelegate
						.createNewActionConf();
			} else {
				painterContainer.painterDelegate
						.setConf(currentActionEvent.actionConf);
			}
		} else {
			ActionEvent e = new ActionEvent();
			ActionConf actionConf = painterContainer.painterDelegate
					.createNewActionConf();
			e.painterContainer = painterContainer.createNewInstance();
			e.actionConf = actionConf;
			e.ticker = new TimeTicker();
			currentActionEvent = e;
			currentAEventList.add(e);
		}
	}

	private ActionEvent onOffCloseOperations(GUIEvent theEvent) {

		// if (!theEvent.isController())
		// return null;

		// int index = controlGroups.indexOf(theEvent.controller());

		// if (index >= 0) {
		propagationManager.setThingActionEvent(thingActionEvent);
		propagationManager.setCurrentActionEvent(currentActionEvent);
		propagationManager.controlEvent(theEvent);

		if (theEvent.name().equals(ON)) {
			currentActionEvent.actionConf.put(ON, 1F);

		} else if (theEvent.name().equals(OFF)) {
			currentActionEvent.actionConf.put(OFF, 1F);

		} else if (theEvent.name().equals(TICKERS)) {

			if (theEvent.button != null) {
				tickersList.setPosition(theEvent.button.getX() + 85, 20);
			} else {
				tickersList.setPosition(lastX + 85, 20);
			}
			tickersList.setDrawable(true);

		} else if (theEvent.name().equals(PROPAGATION)) {
			propagationManager.showform(lastX + 175, 20);
//		} else if (theEvent.name().equals(CORNERPIN)) {
//			currentActionEvent.painterContainer.ks.toggleCalibration();

		} else if (theEvent.name().equals(CLOSE)
				|| theEvent.name().equals(CLEAR)) {

			// cuando cerramos uno de los subformularios, hemos de
			// actualizar esa información en la configuración del
			// momento de ese thing
			painterContainer.painterDelegate.hideForm();
			ActionEvent actionEvent = currentActionEvent;
			currentActionEvent = null;

			if (theEvent.name().equals(CLEAR)) {
				actionEvent.actionConf = null;
			}

			InterfazPlayPause emNit = (InterfazPlayPause) painterContainer.painterDelegate;
			emNit.pause();
			painterContainer = null;

			return actionEvent;
		}
		// }

		return null;
	}

	private void closeRendererListIfSelect(GUIEvent theEvent) {
		if (theEvent.controller() == closeButton) {
			actionEvents = null;
			doing = false;
			scrollList.setDrawable(false);
			tickersList.setDrawable(false);
			scrollList.setPosition(-100, 0);
			currentPosition = null;

		}
	}

	public boolean draw(PApplet pApplet) {

		if (currentPosition != null) {
			pApplet.stroke(255);
			pApplet.line(currentPosition.x, currentPosition.y, currentThing.x,
					currentThing.y);
		}

		if (doing && currentThing != null && currentActionEvent != null) {
			currentActionEvent.update(pApplet, currentThing);
			return true;
		}

		return false;

	}

	public boolean addPainter(ThingPainterDelegate thingPainterDelegate) {

		CircleButton b = guiFactory.newCircleButton(
				thingPainterDelegate.getName(), scrollList.getX(),
				scrollList.getY(), 30);

		b.setGrabbable(true);
		b.setStatic(false);
		scrollList.add(b);
		buttons.add(b);
		scrollList.setDrawable(false);

		// MANAGE TURN ON/OFF AND HIDE SUBFORM
		ButtonList form = guiFactory.newButtonList(
				thingPainterDelegate.getName() + "form", scrollList.getX(),
				scrollList.getY(), 30, 20);

		Button clear = guiFactory.newButton(CLEAR, scrollList.getX(),
				scrollList.getY(), 30, 20);
		form.add(clear);

		Button closeButton = guiFactory.newButton(CLOSE, scrollList.getX(),
				scrollList.getY(), 30, 20);
		form.add(closeButton);

		PainterContainer pc = new PainterContainer();

		if (thingPainterDelegate instanceof CornerPin) {

			Button tickers = guiFactory.newButton(CORNERPIN, scrollList.getX(),
					scrollList.getY(), 30, 20);
			form.add(tickers);

			pc.setup(pApplet, thingPainterDelegate, form, guiFactory);

		} else {
			pc.painterDelegate = thingPainterDelegate;
			pc.painterDelegate.setup(pApplet, controlFacade, form, guiFactory);

		}

		boolean ret = super.add(pc);

		if (thingPainterDelegate instanceof TickerListener) {
			Button tickers = guiFactory.newButton(TICKERS, scrollList.getX(),
					scrollList.getY(), 30, 20);
			form.add(tickers);

			Button propaga = guiFactory.newButton(PROPAGATION,
					scrollList.getX(), scrollList.getY(), 30, 20);
			form.add(propaga);
		}

		if (thingPainterDelegate instanceof TimeRunner) {
			Button on = guiFactory.newButton(ON, scrollList.getX(),
					scrollList.getY(), 30, 20);
			form.add(on);

			Button off = guiFactory.newButton(OFF, scrollList.getX(),
					scrollList.getY(), 30, 20);
			form.add(off);
		}

		// thingPainterDelegate.setup(pApplet, controlFacade, form, guiFactory);
		form.setDrawable(false);
		controlGroups.add(form);
		return ret;
	}

	public void addTicker(Ticker ticker) {
		add(ticker);
	}

	public void add(Ticker ticker) {
		tickers.add(ticker);
		Button tickerButton = guiFactory.newButton(ticker.getName(), 0, 0, 30,
				20);
		tickersList.add(tickerButton);
		tickersList.setDrawable(false);
	}
}
